---
section: 50-Guides
name: Stylesheet extraction
---

# Stylesheet Extraction

Stylesheet extraction is **highly recommended** for all component libraries and applications, so that generated class names can be combined and de-duplicated into one external stylesheet. This allows you to enjoy the decreased stylesheet size that comes with atomic styling.

There are two types of stylesheet extraction:

- Platform stylesheet extraction
- Parcel / Webpack stylesheet extraction

## Which type should I use?

If your package is a component library, use our **platform stylesheet extraction**. This includes Atlassian Design System packages like `@atlaskit/button` or any other package that is treated as a platform offering or used across products or repositories.

If your package exists in the same codebase as, and is _directly consumed_ by, a Webpack or Parcel app, use **Parcel stylesheet extraction** or **Webpack stylesheet extraction** depending on what bundler your app uses.

Note that Parcel and Webpack are the only bundlers we support.

## Platform stylesheet extraction

Platform stylesheet extraction only works if you use Babel to build your component library. Note that we do not recommend nor support using bundlers (e.g. Webpack or Parcel) to build your component library, because bundlers are appropriate for web apps (e.g. Jira) and not for component libraries.

> **Warning**<br/>
> Ensure that any apps that import your component library also have the Compiled Webpack or Parcel plugins installed (`@compiled/webpack-loader` or `@compiled/parcel-config`), otherwise the order in which the styles are applied will become unpredictable. This can be an issue if you have styles that overlap, e.g. if you mix `padding` and `paddingTop` in the same component, or have `@media` queries that potentially overlap.<br/><br/>
> If the apps that import your component library use other bundlers like Vite or Next.js, or if your apps cannot install the Compiled Webpack or Parcel plugins, stylesheet extraction will still work! However, you must make sure that within each component, you should _never_ mix any CSS properties or styles that overlap.

Add `@compiled/babel-plugin-strip-runtime` to your Babel configuration, with `extractStylesToDirectory` set as an option. Set `source` to the folder your component library's source code is defined in, and `dest` to the folder your component library's build output is generated to.

For example:

```js
// babel.config.js
module.exports = {
  plugins: [
    // This will handle all `token()` calls outside of
    // Compiled usages
    '@atlaskit/tokens/babel-plugin',

    // ↓↓ Compiled should run last ↓↓
    [
      '@compiled/babel-plugin',
      {
        transformerBabelPlugins: ['@atlaskit/tokens/babel-plugin'],
      },
    ],
    [
      '@compiled/babel-plugin-strip-runtime',
      {
        extractStylesToDirectory: {
          source: 'src',
          dest: 'dist',
        },
      },
    ],
  ],
};
```

Your `dest` may vary depending on how you generate your `dist/` folder in your component library. For example, if you have mutliple `cjs` and `esm` distributions, those will each need a separate `dest` through Babel's environment-specific configuration.

In each component library's `package.json` file, you will also need to add `"sideEffects": ["**/*.compiled.css"]`, to ensure that the Compiled stylesheets that are generated are exempt from Webpack's and Parcel's tree-shaking (which would delete the stylesheets!):

```json
{
  "name": "@example/my-component-library",
  // …
  "dependencies": {
    // Replace "version" with the latest version
    "@compiled/react": "^version"
  },
  // …
  "sideEffects": ["**/*.compiled.css"]
  // …
}
```

To test whether you've set up stylesheet extraction correctly, use your component library's usual build command (e.g. `yarn build`). Inside the `dist` folder, you should see some `.compiled.css` stylesheets generated, one for each `.tsx` file that uses `@compiled/react`.

For example, if you have a file with the path `packages/design-system/button/dist/cjs/button.js` that uses Compiled, you can expect there to be a corresponding `packages/design-system/button/dist/cjs/button.compiled.css`.

## Parcel stylesheet extraction

If you are using a web app that uses Parcel, first install the [Parcel loader](https://compiledcssinjs.com/docs/installation#installation-methods).

Then configure the `extract` plugin to `true` in your Compiled configuration. For example:

```json
// .compiledcssrc
{
  "extract": true, // <-- add this
  "transformerBabelPlugins": [["@atlaskit/tokens/babel-plugin"]]
}
```

Note that stylesheet extraction feature is disabled on local development due to a [known issue](https://github.com/atlassian-labs/compiled/issues/1306).

See the [`@compiled/parcel-config` documentation](https://compiledcssinjs.com/docs/pkg-parcel-config#options) for information about other configuration options.

## Webpack stylesheet extraction

If your web app uses Webpack, first install the [webpack loader](/installation#webpack).

Then configure the `extract` option to `true` in the webpack loader and turn on the extract plugin.

```diff
// webpack.config.js
+const { CompiledExtractPlugin } = require('@compiled/webpack-loader');

module.exports = {
	module: {
		rules: [
			{
				test: /\.(js|ts|tsx)$/,
				exclude: /node_modules/,
				use: [
					{ loader: 'babel-loader' },
					{
						loader: '@compiled/webpack-loader',
+						options: {
+							extract: true,
+						},
					},
				],
			},
		],
	},
+	plugins: [
+		new CompiledExtractPlugin(),
+	],
};
```

For more configuration options see the [loader package docs](/pkg-webpack-loader#options).

### CSS configuration

Add loaders to handle and extract found styles. We support and recommend [`mini-css-extract-plugin`](https://github.com/webpack-contrib/mini-css-extract-plugin/); we don't currently support other CSS loaders. Note: `mini-css-extract-plugin` dropped support for Webpack v4 in 2.0.0, Webpack v4 users will need to use `mini-css-extract-plugin@1.6.2`.

```bash
npm i css-loader mini-css-extract-plugin --save-dev
```

If you don't already handle `.css` files in your `webpack.config.js`, you can update it like this:

```diff
// webpack.config.js
+const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
	module: {
		rules: [
			{
				test: /\.(js|ts|tsx)$/,
				exclude: /node_modules/,
				use: [
					{ loader: 'babel-loader' },
					{
						loader: '@compiled/webpack-loader',
						options: {
							extract: true,
						},
					},
				],
			},
+			{
+				test: /\.css$/i,
+				use: [MiniCssExtractPlugin.loader, 'css-loader'],
+			},
		],
	},
	plugins: [
// Hash your files unless it's explicitly unnecessary in your build system.
// To achieve this, pass the filename option to the MiniCssExtractPlugin,
// including [contenthash] in the name.
+		new MiniCssExtractPlugin({ filename: '[name].[contenthash].css' }),
		new CompiledExtractPlugin(),
	],
};
```

Note that we don't currently support `style-loader` for loading `css` files from Compiled. If you are using `style-loader`, or you're using a different loader for your `css` files already, you can use regular expressions to ensure that both Compiled's `css` files and your other `css` files are loaded correctly:

```diff
// webpack.config.js
+const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
	module: {
		rules: [
			{
				test: /\.(js|ts|tsx)$/,
				exclude: /node_modules/,
				use: [
					{ loader: 'babel-loader' },
					{
						loader: '@compiled/webpack-loader',
						options: {
							extract: true,
						},
					},
				],
			},
+			{
+				test: /compiled-css\.css$/i,
+				use: [MiniCssExtractPlugin.loader, 'css-loader'],
+			},
			// The following loader will be used for css files that are not from Compiled.
			{
-				test: /\.css$/i,
+				test: /(?<!compiled-css)(?<!\.compiled)\.css$/,
				// Put your existing css loader configuration here
				use: ['style-loader', 'css-loader'],
			},
		],
	},
	plugins: [
		new MiniCssExtractPlugin({ filename: '[name].[contenthash].css' }),
		new CompiledExtractPlugin(),
	],
};
```

All extracted styles will be placed in a file called `compiled-css.css`.

### CSS minification

Turn on the [minimizer plugin](https://github.com/webpack-contrib/mini-css-extract-plugin/#minimizing-for-production).

```bash
npm i css-minimizer-webpack-plugin --save-dev
```

```diff
// webpack.config.js
+const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');

module.exports = {
+	mode: 'production',
	module: {
		rules: [
			{
				test: /\.(js|ts|tsx)$/,
				exclude: /node_modules/,
				use: [
					{ loader: 'babel-loader' },
					{
						loader: '@compiled/webpack-loader',
						options: {
							extract: true,
						},
					},
				],
			},
			{
				test: /\.css$/i,
				use: [MiniCssExtractPlugin.loader, 'css-loader'],
			},
		],
	},
	plugins: [
		new MiniCssExtractPlugin({ filename: '[contenthash].[name].css' })
		new CompiledExtractPlugin(),
	],
+	optimization: {
+		minimizer: [
+			'...',
+			new CssMinimizerPlugin(),
+		],
+	},
};
```
